<script setup>
const props = defineProps({
  direction: {
    type: String,
    default: 'column', // row column
  },
  gap: {
    type: String,
    default: '5px',
  },
  speed: {
    type: Number,
    default: 48, // 帧
  },
  // 是否无缝
  isSeamless: {
    type: Boolean,
    default: true,
  },
})
const marquee = ref(null)
const [DefineTemplate, ReuseTemplate] = createReusableTemplate()
const stop = ref(false)
const over = ref(false)
const tagSize = ref(1)
const computedStyle = computed(() => {
  const { direction, gap, speed } = props
  return {
    'flex-direction': direction,
    'animation': `${direction === 'row' ? 'x' : 'y'}-marquee ${tagSize.value / speed}s linear 0s infinite`,
    'animation-play-state': stop.value || over.value ? 'paused!important' : 'running!important',
    [direction === 'row' ? 'height' : 'width']: '100%',
  }
})

watch(() => [stop.value, over.value], () => {
  if (!stop.value) {
    marquee.value.scroll(0, 0)
  }
  if (stop.value || over.value) {
    marquee.value.querySelectorAll('.mtarget').forEach((item) => {
      item.style.animationName = 'unset'
      item.style.transform = 'translateX(0) !important'
      // 触发重绘
      const ch = item.clientHeight
    })
  }
})

onMounted(() => {
  const ob = new IntersectionObserver((entries) => {
    if (!props.isSeamless) {
      stop.value = false
    }
    for (const entry of entries) {
      if (!stop.value)
        entry.target.style.sort = 1 - entry.isIntersecting
    }
  }, {
    threshold: 0, // 0: 刚刚交叉 1：完全交叉
  })
  const target = marquee.value.querySelectorAll('.mtarget')
  target.forEach((item) => {
    ob.observe(item)
  })
  const rob = new ResizeObserver((entries) => {
    tagSize.value = entries?.[0]?.target?.[props.direction === 'row' ? 'clientWidth' : 'clientHeight']
    if (!props.isSeamless) {
      over.value = tagSize.value <= marquee.value?.[props.direction === 'row' ? 'clientWidth' : 'clientHeight']
    }
  })
  rob.observe(target[0])// 手动触发
  function triggerResize(target) {
    const width = target.style.width
    target.style.width = `${target.offsetWidth + 1}px`;
    target.style.width = width
  }

  // 调用此函数触发观察器
  triggerResize(target[0])
  onBeforeUnmount(() => {
    target.forEach((item) => {
      ob.unobserve(item)
    })
    rob?.disconnect()
  })
})
</script>

<template>
  <DefineTemplate>
    <div
      class="mtarget flex"
      :style="computedStyle"
    >
      <slot></slot>
    </div>
  </DefineTemplate>
  <div
    ref="marquee"
    class="marquee-list wh-full flex" :style="{
      'overflow': stop ? 'auto' : 'hidden',
      gap,
      'flex-direction': direction,
    }"
    @mouseenter.stop="stop = true"
    @mouseleave.stop="stop = false"
  >
    <ReuseTemplate />
    <ReuseTemplate v-if="isSeamless" v-show="!stop" />
    <ReuseTemplate v-if="isSeamless" v-show="!stop" />
  </div>
</template>

<style scoped lang="scss">
.marquee-list {
  --direction: column;
  align-items: center;
  .mtarget {
  }
}
</style>

<style>
@keyframes x-marquee {
  0% {
    transform: translateX(0);
  }
  5% {
    transform: translateX(0);
  }
  100% {
    transform: translateX(-100%);
  }
}
@keyframes y-marquee {
  0% {
    transform: translateY(0);
  }
  5% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-100%);
  }
}
</style>
